<template>
  <div class="category-management">
    <el-card>
      <template #header>

        <div>
          <MultiQuery v-if="pageData.column.length>0" ref="queryRefs" :search-handler="submit"
                      :select-ref-map="selectRefMap" :page-column="pageData.column"/>
        </div>

        <div class="card-header">
          <div>
            <el-checkbox-group v-if="(pageData?.api?.batchDeleteUrl||pageData?.api?.listUrl)&&checkedList"
                               v-model="checkedList" size="small">
              <el-checkbox-button v-for="id in checkedList" :key="id" :value="id">
                {{ id }}
              </el-checkbox-button>
            </el-checkbox-group>
            <div style="text-align: left">{{ pageName }}管理</div>
          </div>

          <div>
            <!--            <span>{{checkedList}}</span>-->
            <el-button v-if="pageData?.api?.batchDeleteUrl&& checkedList?.length>0" type="danger" @click="deleteSelected">删除选中</el-button>
            <el-button v-if="pageData?.api?.listUrl&& checkedList?.length>0" @click="exportSelected" type="primary">
              导出选中
            </el-button>
            <el-button v-if="pageData?.api?.add&&insertPermission" type="primary" @click="showDialog = true;resetCurrent()">
              新增{{ pageName }}
            </el-button>
            <el-button v-if="exportPermission" @click="exportPage" type="success">导出当前页</el-button>
          </div>
        </div>
      </template>

      <el-table :data="pageData.data" border stripe>
        <el-table-column v-if="(pageData?.api?.batchDeleteUrl||pageData?.api?.listUrl)&&idProp" #default="{row}"
                         label="多选">
          <el-checkbox v-model="checkedList" :label="'选中'+row[idProp]" size="large" border
                       :value="row[idProp]"></el-checkbox>
        </el-table-column>
        <el-table-column
            v-for="col in pageData.column"
            :key="col.prop"
            :label="col.label"
            :prop="col.prop"
        >
          <template #default="{ row }">
            <el-tag v-if="col.type === 'tag'">{{ row[col.prop] }}</el-tag>
            <el-switch disabled v-model="row[col.prop]" v-if="col.type === 'toggle'"></el-switch>
            <el-rate v-else-if="col.type === 'rating'" v-model="row[col.prop]" disabled show-score></el-rate>
            <el-image v-else-if="col.type === 'img'" :src="baseURL+col.fetchUrl+row[col.prop]" fit="cover"
                      style="height: 100px"></el-image>
            <span v-else-if="col.type==='password'">********</span>
            <template v-else-if="col.type === 'select'">
              <el-link v-if="col?.clickUrlPrefix" @click="router.push(col?.clickUrlPrefix+row[col.prop])">
                  {{
                selectRefMap.get(col.label) ? (selectRefMap.get(col.label).find(item => item.value === row[col.prop]) ? selectRefMap.get(col.label).find(item => item.value === row[col.prop]).label : row[col.prop]) : row[col.prop]
                }}
              </el-link>
              <span v-else>
                {{
                  selectRefMap.get(col.label) ? (selectRefMap.get(col.label).find(item => item.value === row[col.prop]) ? selectRefMap.get(col.label).find(item => item.value === row[col.prop]).label : row[col.prop]) : row[col.prop]
                }}
              </span>
            </template>
            <template v-else-if="col.type === 'mapping'">
              <el-dropdown>
                <span class="el-dropdown-link">
                  查看{{ col.label }}
                  <el-icon class="el-icon--right">
                    <arrow-down/>
                  </el-icon>
                </span>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item v-for="o in row[col.prop]">
                      <el-tag type="primary">{{ o[col.mappingRef.mappingListLabel] ? o[col.mappingRef.mappingListLabel] : o[col.mappingRef.mappingListProp] }}</el-tag>
                    </el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
            </template>
            <template v-else-if="row[col.prop]&&(col.type==='text'||col.type==='textarea')">
              {{row[col.prop].length>10?row[col.prop].substring(0,10)+'...':row[col.prop]}}
            </template>
          </template>
        </el-table-column>
        <el-table-column v-if="(pageData?.api?.update&&updatePermission)||(pageData?.api?.delete&&deletePermission&&idProp)" label="操作" width="180">
          <template #default="{ row }">
            <el-button
                v-if="pageData?.api?.update&&updatePermission"
                size="small"
                type="primary"
                @click="editCurrent(row)"
            >
              {{pageData?.updateAlias?pageData?.updateAlias:'编辑'}}
            </el-button>
            <el-button
                v-if="pageData?.api?.delete&&deletePermission&&idProp"
                size="small"
                type="danger"
                @click="deleteCurrent(row[idProp])"
            >
              {{pageData?.deleteAlias?pageData?.deleteAlias:'删除'}}
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <el-pagination
          :current-page="pagination.current"
          :page-size="pagination.size"
          :page-sizes="[10, 20, 50, 100]"
          :total="pagination.total"
          class="pagination"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
      />
    </el-card>

    <el-dialog
        v-model="showDialog"
        :title="isEdit ? '编辑' : '添加'"
        width="500px"
    >
      <el-form :model="currentObject" label-width="80px">
        <el-form-item v-for="col in pageData.column"
                      :label="col.label"
                      :prop="col.prop">
          <!--            选择框-->
          <template v-if="col.type === 'select'">
            <el-select v-if="col.selectRef" v-model="currentObject[col.prop]" :disabled="!col.allowEdit"
                       placeholder="请选择">
              <el-option
                  v-for="item in selectRefMap.get(col.label)"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
              />
            </el-select>
            <el-input v-else v-model="currentObject[col.prop]" :disabled="!col.allowEdit" placeholder="请输入"/>
          </template>
          <template v-else-if="col.type === 'mapping'">
            <el-select multiple v-if="col.mappingRef" v-model="currentObject[col.prop]" :disabled="!col.allowEdit"
                       placeholder="请选择">
              <el-option
                  v-for="item in selectRefMap.get(col.label)"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
              />
            </el-select>
            <el-input v-else v-model="currentObject[col.prop]" :disabled="!col.allowEdit" placeholder="请输入"/>
          </template>
          <!--            多选框-->
          <template v-else-if="col.type === 'checkbox'">
            <el-checkbox-group v-if="col.selectRef" v-model="currentObject[col.prop]" :disabled="!col.allowEdit">
              <el-checkbox v-for="item in selectRefMap.get(col.label)" v-if="selectRefMap" :key="item.value"
                           :label="item.value">{{
                  item.label
                }}
              </el-checkbox>
            </el-checkbox-group>
            <el-input v-else v-model="currentObject[col.prop]" :disabled="!col.allowEdit" placeholder="请输入"/>
          </template>
          <template v-else-if="col.type === 'date-picker'">
            <el-date-picker v-model="currentObject[col.prop]" :disabled="!col.allowEdit" placeholder="选择日期"
                            type="datetime"/>
          </template>
          <template v-else-if="col.type === 'textarea'">
            <el-input v-model="currentObject[col.prop]" :disabled="!col.allowEdit" placeholder="请输入"
                      type="textarea"></el-input>
          </template>
          <template v-else-if="col.type === 'radio'">
            <el-radio-group v-model="currentObject[col.prop]" :disabled="!col.allowEdit">
              <el-radio v-for="item in selectRefMap.get(col.label)" :key="item.value" :label="item.value">{{
                  item.label
                }}
              </el-radio>
            </el-radio-group>
          </template>
          <template v-else-if="col.type === 'rating'">
            <el-rate v-model="currentObject[col.prop]" :disabled="!col.allowEdit" :max="5" show-score></el-rate>
          </template>
          <template v-else-if="col.type === 'toggle'">
            <el-switch v-model="currentObject[col.prop]" :disabled="!col.allowEdit"></el-switch>
          </template>
          <template v-else-if="col.type === 'img'">
            <el-upload
                class="avatar-uploader"
                :action="baseURL+col.url"
                :show-file-list="false"
                :on-success="handleImgSuccess"
                :before-upload="(file)=>{beforeImgUpload(file,col.prop)}"
            >
              <template v-if="currentObject[col.prop]">
                <img :src="baseURL+col.fetchUrl+currentObject[col.prop]" height="100px" class="avatar"/>

              </template>
              <el-icon v-else class="avatar-uploader-icon">
                <Plus/>
              </el-icon>
            </el-upload>
            <el-button v-if="currentObject[col.prop]" style="margin-left: 10px" @click="currentObject[col.prop]=null"
                       circle size="large" type="danger" icon="Delete"></el-button>
          </template>
          <template v-else>
            <el-input v-model="currentObject[col.prop]" :disabled="!col.allowEdit"
                      :type="col.type==='password'?'password':'text'" placeholder="请输入"></el-input>
          </template>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="showDialog = false">取消</el-button>
        <el-button type="primary" @click="submitObject">提交</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import {ref, onMounted, watch} from 'vue'
import {useStore} from 'vuex'
import {ElMessage, ElMessageBox} from 'element-plus'
import api from "@/api/index.js";
import handleExport from "@/utils/xlsxExportUtil.js";
import MultiQuery from "@/components/MultiQuery.vue";
import router from "@/router/router.js";

const store = useStore()
//查询条件构造器
const queryColumn = ref([])
const queryRefs = ref([])
const querySearchBuilder = ref([])
const checkedList = ref([])

const submit = () => {
  loadData()
}

//表格构造器代码
// const
const pageName = ref('?')
const idProp = ref('')
const pageData = ref({column: [], data: []})
const props = defineProps({
  apiUrl: {
    type: String,
    required: true
  },
  insertPermission: {
    type: Boolean,
    default: false
  },
  updatePermission: {
    type: Boolean,
    default: false
  },
  deletePermission: {
    type: Boolean,
    default: false
  },
  exportPermission: {
    type: Boolean,
    default: false
  },
})

const showDialog = ref(false)
const isEdit = ref(false)
const currentObject = ref({})
const selectRefMap = ref(new Map())

const editingFileName = ref('')
const handleChangeFile = (name) => {
  editingFileName.value = name
}
const handleImgSuccess = (res, file) => {
  console.log(res)
  currentObject.value[editingFileName.value] = res.url
}

const beforeImgUpload = (file, prop) => {
  editingFileName.value = prop
  const isIMG = file.type === 'image/jpeg' || file.type === 'image/png'
  const isLt5M = file.size / 1024 / 1024 < 5

  if (!isIMG) {
    ElMessage.error('上传图片只能是JPG或PNG格式!')
  }
  if (!isLt5M) {
    ElMessage.error('上传图片大小不能超过 5MB!')
  }
  return isIMG && isLt5M
}

const pagination = ref({
  current: 1,
  size: 10,
  total: 0
})


const loadSelection = async (column) => {
  try {
    if (column.selectRef?.apiUrl && column?.type === 'select' || column?.type === 'checkbox' || column?.type === 'radio') {
      let prop = column.selectRef
      // console.log(column.selectRef)
      if (selectRefMap.value.has(prop.mapLabel)) {
        return selectRefMap.value.get(prop.mapLabel)
      } else {
        api.get(prop.apiUrl).then(resp => {
          // console.log(resp)
          let res = resp.data.map(item => {
            // console.log(column.label+" "+item[prop.mapProp]+"-"+item[prop.mapLabel])
            return {value: item[prop.mapProp], label: item[prop.mapLabel]}
          })
          selectRefMap.value.set(column.label, res);
        })
      }
    } else if (column.mappingRef?.mappingListUrl && column?.type === 'mapping') {
      let prop = column.mappingRef
      // console.log(column.mappingRef)
      if (selectRefMap.value.has(prop.mappingListLabel)) {
        return selectRefMap.value.get(prop.mappingListLabel)
      } else {
        api.get(prop.mappingListUrl).then(resp => {
          // console.log(resp)
          let res = resp.data.map(item => {
            // console.log(column.label+" "+item[prop.mapProp]+"-"+item[prop.mapLabel])
            return {value: item[prop.mappingListProp], label: item[prop.mappingListLabel]}
          })
          selectRefMap.value.set(column.label, res);
          // console.log(res)
        })
      }
    }
  } catch (e) {
    console.error(e)
  }
}

//xlsx导出功能
const exportPage = () => {
  let propMap = new Map()//{键-键名称}
  pageData.value.column.forEach(column => {
    propMap.set(column.prop, column.label)
  })
  let dstList = []
  for (const row of pageData.value.data) {
    // row{id:??,name:??}
    let o = {}
    propMap.forEach((value, key) => {
      o[value] = row[key]
    })
    dstList.push(o)
  }
  handleExport(dstList, pageName.value)
}
const exportSelected = () => {
  if (pageData.value?.api?.listUrl && checkedList.value.length >= 0) {
    //construct query condition
    let queryString = '';
    for (const id of checkedList.value) {
      queryString += id + ","
    }
    queryString = queryString.slice(0, -1)
    console.log(queryString)
    api.getWithQuery(pageData.value?.api?.listUrl, [{
      operator: "AND",
      field: idProp.value,
      fieldName: '',
      type: 'listQuery',
      method: 'IN',
      value: queryString
    }]).then(resp => {
      let propMap = new Map()//{键-键名称}
      pageData.value.column.forEach(column => {
        propMap.set(column.prop, column.label)
      })
      let dstList = []
      for (const row of resp.data) {
        // row{id:??,name:??}
        let o = {}
        propMap.forEach((value, key) => {
          o[value] = row[key]
        })
        dstList.push(o)
      }
      handleExport(dstList, pageName.value)
      console.log(resp)
    }).catch(e=>{
      ElMessage.error("导出失败")
    })
  } else {
    ElMessage.error("请选择要导出的行")
  }
}

//初始化
const init = async () => {
  // const resp = await api.get('/api/category/list')
  // pageData.value = resp.data
  queryColumn.value = pageData.value.column.map(column => {
    return {
      value: column.prop,
      label: column.label,
      type: column.type
    }
  })
  for (const column of pageData.value.column) {
    if (column.isId) {
      idProp.value = column.prop
    }
    if (column.selectRef) {
      loadSelection(column)
    }
  }
}

const loadData = () => {
  // selectRefMap.value.set('mapProp', [List])
  api.getPage(props.apiUrl, {
        pageNum: pagination.value.current,
        pageSize: pagination.value.size
      }, queryRefs.value?.querySearchBuilder?queryRefs.value?.querySearchBuilder:[]//将查询器加入Header中
  ).then(resp => {
    pageData.value = resp.data
    pagination.value.total = resp.data.total
    // pagination.value.current = resp.data.page
    pageName.value = resp.data?.name
    init()
    // console.log(resp)
  }).catch(e => {
    ElMessage.error("加载失败" + e)
  })
}

const editCurrent = (current) => {
  isEdit.value = true
  currentObject.value = {}
  for (let k in current) {
    let col = pageData.value.column.find(column => column.prop === k);
    if (col?.type === 'mapping') {
      if (current[k]) {
        currentObject.value[k] = current[k].map(item => item[col.mappingRef.mappingListProp])
      } else {
        currentObject.value[k] = []
      }
    } else {
      currentObject.value[k] = current[k]
    }
  }
  showDialog.value = true
}

const submitObject = () => {
  if (isEdit.value) {
    api.put(pageData.value.api.update, currentObject.value).then(resp => {
      ElMessage.success('修改成功')
      loadData()
      resetCurrent()
      showDialog.value = false
    }).catch(e => {
      ElMessage.error('修改失败')
    })
  } else {
    // let tmpName = currentObject.value.permissionName;
    // let tmpDesc = currentObject.value.description;
    // let arr = ['查询','添加','修改','删除']
    // let arr1 = ['QUERY','ADD', 'ALTER', 'DELETE']
    // for (let i = 0; i < arr.length; i++) {
    //   currentObject.value.permissionName = tmpName+arr1[i]
    //   currentObject.value.description = arr[i]+tmpDesc
    //   api.post(pageData.value.api.add, currentObject.value).then(resp => {
    //     ElMessage.success('添加成功')
    //     if(i===arr.length-1) {
    //       loadData()
    //       resetCurrent()
    //       showDialog.value = false
    //     }
    //
    //   }).catch(e=>{
    //     ElMessage.error('添加失败')
    //   })
    // }
    api.post(pageData.value.api.add, currentObject.value).then(resp => {
      ElMessage.success('添加成功')
      loadData()
      resetCurrent()
      showDialog.value = false
    }).catch(e => {
      ElMessage.error('添加失败')
    })
  }
}

const deleteCurrent = (id) => {
  ElMessageBox.confirm('确定要删除这个内容吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
      .then(() => {
        api.delete(pageData.value.api.delete + '/' + id).then(resp => {
          ElMessage.success('删除成功')
          showDialog.value = false
          loadData()
        }).catch(e => {
          ElMessage.error('删除失败')
        })
      })
      .catch(() => {
        ElMessage.info('已取消删除')
      })
}
const deleteSelected = () => {
  ElMessageBox.confirm('确定要删除选中内容吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
      .then(() => {
        if (pageData.value?.api?.batchDeleteUrl && checkedList.value.length >= 0) {
          api.post(pageData.value?.api?.batchDeleteUrl, checkedList.value).then(e => {
            console.log(e)
            loadData()
          })
        } else {
          ElMessage.error("请选择要删除的行")
        }
      })
      .catch(() => {
        ElMessage.info('已取消删除')
      })
}


const resetCurrent = () => {
  currentObject.value = {}
  for (let column of pageData.value.column) {
    currentObject.value[column.prop] = null
  }
  isEdit.value = false
}

const handleSizeChange = (size) => {
  pagination.value.size = size
  loadData()
}

const handleCurrentChange = (current) => {
  pagination.value.current = current
  loadData()
}


//用于实时应用props的内容
const refresh = () => {
  pageData.value = {column: [], data: []}
  loadData()
}
watch(
    () => props.apiUrl,
    (newUrl, oldUrl) => {
      if (newUrl !== oldUrl) {
        refresh()
      }
    }
)
//表格构造器代码End
const baseURL = api.getInstance().defaults.baseURL

onMounted(() => {
  loadData()
})
</script>

<style scoped>
.category-management {
  padding: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.pagination {
  margin-top: 20px;
  text-align: center;
}

.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}
</style>